package com.zhihaoliang.coroutine.buss.dispatcher

import com.zhihaoliang.coroutine.base.BaseActivity
import com.zhihaoliang.coroutine.databinding.DispatcherActivityBinding
import com.zhihaoliang.coroutine.util.log
import kotlinx.coroutines.*

/**
 * @author 支豪亮
 * @date 2022/10/21 14:08
 * @des 协成调度器
 */
class DispatcherActivity : BaseActivity<DispatcherActivityBinding>(), IDispatcher {

    private val mainScope = MainScope()

    override fun initDataBinding() = DispatcherActivityBinding.inflate(layoutInflater)

    override fun bindData() {
        super.bindData()
        dataBinding.callback = this
    }


    @OptIn(DelicateCoroutinesApi::class)
    override fun onDispatcherType() {
        mainScope.launch { // 运行在父协程的上下文中，即 runBlocking 主协程
            log("no param", coroutineContext)
        }

        mainScope.launch(Dispatchers.Unconfined) { // 不受限的——将工作在主线程中
            log("Dispatchers.Unconfined", coroutineContext)
        }

        mainScope.launch(Dispatchers.Default) { // 将会获取默认调度器
            log("Dispatchers.Default", coroutineContext)
        }

        mainScope.launch(newSingleThreadContext("SingleThread")) { // 将使它获得一个新的线程
            log("SingleThread", coroutineContext)
        }

        GlobalScope.launch {
            log("GlobalScope", coroutineContext)
        }
    }

    override fun onUnconfinedVsConfined() {
        mainScope.launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
            log("Unconfined      : start", coroutineContext)
            delay(500)
            log("Unconfined      : end", coroutineContext)
        }

        mainScope.launch { // context of the parent, main runBlocking coroutine
            log("main runBlocking: start", coroutineContext)
            delay(1000)
            log("main runBlocking: end", coroutineContext)
        }
    }

    @OptIn(DelicateCoroutinesApi::class)
    override fun onJumpThread() {
        newSingleThreadContext("Ctx1").use { ctx1 ->
            newSingleThreadContext("Ctx2").use { ctx2 ->
                runBlocking(ctx1) {
                    log("Started in ctx1", coroutineContext)
                    withContext(ctx2) {
                        log("Working in ctx2", coroutineContext)
                    }
                    log("Back to ctx1", coroutineContext)
                }
            }
        }
    }

    @OptIn(DelicateCoroutinesApi::class)
    override fun onChild() {
        mainScope.launch { // 启动一个协程来处理某种传入请求（request）
            val request = launch { // 孵化了两个子作业, 其中一个通过 GlobalScope 启动
                GlobalScope.launch {
                    log("job1: I run in GlobalScope and execute independently!",coroutineContext)
                    delay(1000)
                    log("job1: I am not affected by cancellation of the request",coroutineContext)
                } // 另一个则承袭了父协程的上下文
                launch {
                    delay(100)
                    log("job2: I am a child of the request coroutine",coroutineContext)
                    delay(1000)
                    log("job2: I will not execute this line if my parent request is cancelled",coroutineContext)
                }
            }
            delay(500)
            request.cancel() // 取消请求（request）的执行
            delay(1000) // 延迟一秒钟来看看发生了什么
            log("main: Who has survived request cancellation?",coroutineContext)
        }
    }

    override fun onNamed() {
        mainScope.launch {
            log("Started main coroutine",coroutineContext) // 运行两个后台值计算
            val v1 = async(CoroutineName("v1coroutine")) {
                delay(500)
                log("Computing v1",coroutineContext)
                252
            }
            val v2 = async(CoroutineName("v2coroutine")) {
                delay(1000)
                log("Computing v2",coroutineContext)
                6
            }

            launch(Dispatchers.Default + CoroutineName("test")) {
                log("I'm working in thread ${Thread.currentThread().name}",coroutineContext)
            }

            log("The answer for v1 / v2 = ${v1.await() / v2.await()}",coroutineContext)
        }
    }

}